/**
 * Copyright 2010 Victor Egea Hernando
 *
 * RockScript is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * 
 * RockScript is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with RockScript.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef USTRING_H_
#define USTRING_H_

#include "../types.h"

namespace corelib{

class CORELIB_API ustring{

public:
    /*------------------------------------------------------------------
       typedefs & constants
      ------------------------------------------------------------------*/
    // unicode characer type
    typedef uint32 uch;

    /*------------------------------------------------------------------
       typedefs & constants
      ------------------------------------------------------------------*/
    // length position
    static const size npos = 0xFFFFFFFF;

    /*------------------------------------------------------------------
       costructors & destructor
      ------------------------------------------------------------------*/
    // default constructor
    ustring();
    // assign string
    ustring( const char *str );
    // copy constructor
    ustring( const ustring &str );
    // assign string
    ustring( const std::string &str );
    // assign string
    ustring( const uch *ucodes, corelib::size n );

    /*------------------------------------------------------------------
       copy
      ------------------------------------------------------------------*/
    // copy ustring
    void copy( const ustring &str );

    /*------------------------------------------------------------------
       assign
      ------------------------------------------------------------------*/
    // assign string
    void assign( const uch *ucodes, corelib::size n );
    // assign string
    void assign( const std::string &str );
    // assign string
    void assign( const char *str );

    /*------------------------------------------------------------------
       main interface
      ------------------------------------------------------------------*/
    // get substring
    ustring substr( uint32 pos1=0, uint32 pos2=npos );

    // compare binary codes
    int32 compare( const ustring &str ) const;
    // operator '=='
    bool operator==( const ustring& p ) const;
    // operator '<'
    bool operator<( const ustring& p ) const;

    // clear
    void clear( void );

    // is it empty?
    bool empty( void ) const;
    // gets length
    uint32 length( void ) const;
    // is it above the BMP?
    bool above_bmp( void ) const;

    // push back ucs-3 code
    void push_back( uch ch );

    // array operator, gets the unicode char from idx
    uch operator[]( size idx ) const;
    // gets utf8 string inside a string class
    std::string str( void ) const;

    // operator concatenation
    ustring operator+( const std::string &str ) const;
    // operator concatenation
    ustring operator+( const ustring &str ) const;
    // operator concatenation
    ustring operator+( const char *str ) const;

protected:
    /*------------------------------------------------------------------
       typedefs
      ------------------------------------------------------------------*/
    // unicode unit
    typedef uint16 utf16u;

    /*------------------------------------------------------------------
       friend classes
      ------------------------------------------------------------------*/
    // hash function
    friend class ustring_hash;

    /*------------------------------------------------------------------
       util functions
      ------------------------------------------------------------------*/
    // does it have a BOM (Binary Order Mark)?
    bool hasBOM( const char *str );

    /*------------------------------------------------------------------
       data
      ------------------------------------------------------------------*/
    // unicode string
    std::vector<utf16u> _ustr;
    // one or more characters could be over the "Basic Multilingual Plane"
    bool _above_BMP;
    // ustring length
    uint32 _length;

};

/**
 *
 */
class CORELIB_API ustring_hash
{

public:
    //! @brief MurmurHash 2.0. By Austin Appleby
    corelib::uint32 operator()( const corelib::ustring &str ) const;

};

}; // namespace corelib;

// prints the string as hexadecimal values
CORELIB_API std::ostream &operator << ( std::ostream &os, const corelib::ustring &utf8s );

#endif // USTRING_H_
